allwinner: Scan AXP803 FDT node to setup initial power rails
authorAndre Przywara <[email protected]>
Sun, 16 Sep 2018 10:24:05 +0000 (11:24 +0100)
committerAndre Przywara <[email protected]>
Sat, 20 Oct 2018 15:23:59 +0000 (16:23 +0100)
Now that we have a pointer to the device tree blob, let's use that to
do some initial setup of the PMIC:
- We scan the DT for the compatible string to find the PMIC node.
- We switch the N_VBUSEN pin if the DT property tells us so.
- We scan over all regulator subnodes, and switch DC1SW if there is at
least one other node referencing it (judging by the existence of a
phandle property in that subnode).
This is just the first part of the setup, a follow up patch will setup
voltages.

Signed-off-by: Andre Przywara <[email protected]>
plat/allwinner/sun50i_a64/sunxi_power.c

index 48d01d0c2982c70e6cc882c701503eab9fb04474..0d73371a89ed787d63f723212683aa03c93581e4 100644 (file)
@@ -10,6 +10,7 @@
 #include <debug.h>
 #include <delay_timer.h>
 #include <errno.h>
+#include <libfdt.h>
 #include <mmio.h>
 #include <platform_def.h>
 #include <sunxi_def.h>
@@ -126,6 +127,52 @@ static int axp_setbits(uint8_t reg, uint8_t set_mask)
        return rsb_write(AXP803_RT_ADDR, reg, regval);
 }
 
+static bool should_enable_regulator(const void *fdt, int node)
+{
+       if (fdt_getprop(fdt, node, "phandle", NULL) != NULL)
+               return true;
+       if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL)
+               return true;
+       return false;
+}
+
+static void setup_axp803_rails(const void *fdt)
+{
+       int node;
+
+       /* locate the PMIC DT node, bail out if not found */
+       node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803");
+       if (node == -FDT_ERR_NOTFOUND) {
+               WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n");
+               return;
+       }
+
+       if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL))
+               axp_setbits(0x8f, BIT(4));
+
+       /* descend into the "regulators" subnode */
+       node = fdt_first_subnode(fdt, node);
+
+       /* iterate over all regulators to find used ones */
+       for (node = fdt_first_subnode(fdt, node);
+            node != -FDT_ERR_NOTFOUND;
+            node = fdt_next_subnode(fdt, node)) {
+               const char *name;
+               int length;
+
+               /* We only care if it's always on or referenced. */
+               if (!should_enable_regulator(fdt, node))
+                       continue;
+
+               name = fdt_get_name(fdt, node, &length);
+               if (!strncmp(name, "dc1sw", length)) {
+                       INFO("PMIC: AXP803: Enabling DC1SW\n");
+                       axp_setbits(0x12, BIT(7));
+                       continue;
+               }
+       }
+}
+
 int sunxi_pmic_setup(uint16_t socid, const void *fdt)
 {
        int ret;
@@ -148,6 +195,9 @@ int sunxi_pmic_setup(uint16_t socid, const void *fdt)
                pmic = AXP803_RSB;
                NOTICE("BL31: PMIC: Detected AXP803 on RSB.\n");
 
+               if (fdt)
+                       setup_axp803_rails(fdt);
+
                break;
        default:
                NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid);